//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.github.glomadrian.pathloading;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import java.util.Optional;

/**
 * 着色器
 *
 * @since 2021-07-19
 */
public class ColorSeekBar extends Component implements Component.EstimateSizeListener,
        Component.DrawTask, Component.TouchEventListener {
    private int mBackgroundColor = -1;
    private int[] mColors = new int[]{Color.RED.getValue(), 0x9C27B0, 0x3F51B5, 0x03A9F4,
        0x009688, 0x8BC34A, 0xFFEB3B, 0xFF9800, 0x795548, Color.WHITE.getValue()};
    private int c0;
    private int c1;
    private float mAlpha;
    private int mRed;
    private int mGreen;
    private int mBlue;
    private float x1;
    private float y1;
    private OnColorChangeListener mOnColorChangeLister;
    private Context mContext;
    private boolean mIsShowAlphaBar = false;
    private boolean mMovingColorBar;
    private boolean mMovingAlphaBar;
    private Rect mColorRect;
    private static int mThumbHeight = 30;
    private static int mBarHeight = 10;
    private LinearShader mColorGradient;
    private Paint mColorRectPaint;
    private int realLeft;
    private int realRight;
    private int realTop;
    private int mBarWidth;
    private static int mMaxValue = 100;
    private Rect mAlphaRect;
    private int mColorBarValue = 0;
    private int mAlphaBarValue = 0;
    private float mThumbRadius;
    private static int mBarMargin = 5;
    private int mPaddingSize;
    private int mViewWidth;
    private int tag;

    /** ColorSeekBar
     *
     * @param context
     * @param attrs
     */
    public ColorSeekBar(Context context, AttrSet attrs) {
        super(context, attrs);
        this.setEstimateSizeListener(this::onEstimateSize);
        this.setTouchEventListener(this::onTouchEvent);
        this.init(context, attrs, 0, 0);
        invalidate();
    }

    /** ColorSeekBar
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public ColorSeekBar(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.init(context, attrs, defStyleAttr, 0);
    }

    /** init初始化
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     * @param defStyleRes
     */
    protected void init(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {
        this.applyStyle(context, attrs, defStyleAttr, defStyleRes);
    }


    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        this.mViewWidth = widthMeasureSpec;
        int speMode = EstimateSpec.getMode(heightMeasureSpec);
        if (speMode == EstimateSpec.NOT_EXCEED) {
            if (this.mIsShowAlphaBar) {
                this.setEstimatedSize(this.mViewWidth, this.mThumbHeight * 2 + this.mBarHeight * 2 + this.mBarMargin);
            } else {
                this.setEstimatedSize(this.mViewWidth, this.mThumbHeight + this.mBarHeight);
            }
        }
        return false;
    }

    /** applyStyle
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     * @param defStyleRes
     */
    protected void applyStyle(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {
        this.mContext = context;
        this.mMaxValue = attrs.getAttr("ColorSeekBar_maxValue").get().getIntegerValue();
        this.mColorBarValue = attrs.getAttr("ColorSeekBar_colorBarValue").get().getIntegerValue();
        this.mAlphaBarValue = attrs.getAttr("ColorSeekBar_alphaBarValue").get().getIntegerValue();
        this.mIsShowAlphaBar = attrs.getAttr("ColorSeekBar_showAlphaBar").get().getBoolValue();
        this.mBackgroundColor = attrs.getAttr("ColorSeekBar_bgColor").get().getIntegerValue();
        this.mBarHeight =   attrs.getAttr("ColorSeekBar_barHeight").get().getDimensionValue();
        this.mThumbHeight = attrs.getAttr("ColorSeekBar_thumbHeight").get().getDimensionValue();
        this.mBarMargin = attrs.getAttr("ColorSeekBar_barMargin").get().getDimensionValue();
        this.mColors = this.getColorsById(ResourceTable.Strarray_colors);
        ShapeElement element = new ShapeElement();
        element.setRgbColor(RgbColor.fromArgbInt(this.mBackgroundColor));
        this.setBackground(element);
        this.init();
        this.pickColor((float)this.mColorBarValue);
        this.setAlphaValue();
    }

    private int[] getColorsById(int id) {
        int[] colors;
        int j;
        String[] s = this.mContext.getStringArray(id);
        System.out.println("length-----" + s.length);
        colors = new int[s.length];

        for(j = 0; j < s.length; ++j) {
            colors[j] = Color.getIntColor(s[j]);
        }
        return colors;
    }

    private void init() {
        this.realLeft = this.getPaddingLeft() + this.mPaddingSize;
        this.realRight = this.getWidth() - this.getPaddingRight() - this.mPaddingSize;
        this.realTop = this.getPaddingTop() + this.mPaddingSize;
        this.mThumbRadius = (float)(this.mThumbHeight / 2f);
        this.mPaddingSize = (int)this.mThumbRadius;
        this.mBarWidth = this.realRight - this.realLeft;
        this.mColorRect = new Rect(this.realLeft, this.realTop, this.realRight, this.realTop + this.mBarHeight);
        Color[] colors = new Color[this.mColors.length];
        for (int i = 0; i < this.mColors.length;i++){
            colors[i] = new Color(this.mColors[i]);
        }
        this.mColorGradient = new LinearShader(new Point[]{new Point(0, 0), new Point((float)this.mColorRect.getWidth(), 0)},
            null, colors, Shader.TileMode.MIRROR_TILEMODE);
        this.mColorRectPaint = new Paint();
        this.mColorRectPaint.setShader(this.mColorGradient, Paint.ShaderType.LINEAR_SHADER);
        this.mColorRectPaint.setAntiAlias(true);
    }

    /** ColorSeekBar
     *
     * @param context
     * @param x1
     * @param x2
     */
    public ColorSeekBar(Context context, float x1, float x2) {
        super(context);
    }

    @Override
    public void invalidate() {
        super.invalidate();
        this.addDrawTask(this::onDraw);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        tag++;
        if (tag == 1) {
            this.init();
        }
        float colorPosition = (float)this.mColorBarValue / (float)this.mMaxValue * (float)this.mBarWidth;
        Paint colorPaint = new Paint();
        colorPaint.setAntiAlias(true);
        colorPaint.setColor(new Color(this.pickColor(colorPosition)));
        System.out.println("mRed----------------" + this.mRed);
        int[] toAlpha = new int[]{Color.argb(255, this.mRed, this.mGreen, this.mBlue), Color.argb(0, this.mRed, this.mGreen, this.mBlue)};
        canvas.drawRect(this.mColorRect, this.mColorRectPaint);
        float thumbX = colorPosition + (float)this.realLeft;
        float thumbY = (float)(this.mColorRect.top + this.mColorRect.getHeight() / 2);
        canvas.drawCircle(thumbX, thumbY, (float)(this.mBarHeight / 2 + 5), colorPaint);
        Color[] floats = new Color[toAlpha.length];
        for (int i = 0; i < toAlpha.length;i++) {
            floats[i] = new Color(toAlpha[i]);
        }
        Shader thumbShader = new RadialShader(new Point(thumbX, thumbY), this.mThumbRadius, new float[]{},
            floats, Shader.TileMode.MIRROR_TILEMODE);
        Paint thumbGradientPaint = new Paint();
        thumbGradientPaint.setAntiAlias(true);
        thumbGradientPaint.setShader(thumbShader, Paint.ShaderType.RADIAL_SHADER);
        canvas.drawCircle(thumbX, thumbY, (float)(this.mThumbHeight / 2f), thumbGradientPaint);
        if (this.mIsShowAlphaBar) {
            int top = (int)((float)this.mThumbHeight + this.mThumbRadius + (float)this.mBarHeight + (float)this.mBarMargin);
            this.mAlphaRect = new Rect(this.realLeft, top, this.realRight, top + this.mBarHeight);
            Paint alphaBarPaint = new Paint();
            alphaBarPaint.setAntiAlias(true);
            LinearShader alphaBarShader = new LinearShader(new Point[]{new Point(0.0F, 0.0F),
                new Point((float)this.mAlphaRect.getWidth(), 0.0F)}, new float[]{}, floats, Shader.TileMode.MIRROR_TILEMODE);
            alphaBarPaint.setShader(alphaBarShader, Paint.ShaderType.LINEAR_SHADER);
            canvas.drawRect(this.mAlphaRect, alphaBarPaint);
            float alphaPosition = (float)this.mAlphaBarValue / 1.0f * (float)this.mBarWidth;
            float alphaThumbX = alphaPosition + (float)this.realLeft;
            float alphaThumbY = (float)(this.mAlphaRect.top + this.mAlphaRect.getHeight() / 2);
            canvas.drawCircle(alphaThumbX, alphaThumbY, (float)(this.mBarHeight / 2 + 5), colorPaint);
            RadialShader alphaThumbShader = new RadialShader(new Point(alphaThumbX, alphaThumbY), this.mThumbRadius,
                new float[]{}, floats, Shader.TileMode.MIRROR_TILEMODE);
            Paint alphaThumbGradientPaint = new Paint();
            alphaThumbGradientPaint.setAntiAlias(true);
            alphaThumbGradientPaint.setShader(alphaThumbShader, Paint.ShaderType.RADIAL_SHADER);
            canvas.drawCircle(alphaThumbX, alphaThumbY, (float)(this.mThumbHeight / 2f), alphaThumbGradientPaint);
        }
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        switch(touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                this.x1 = getTouchX(touchEvent, 0, component);
                this.y1 = getTouchY(touchEvent, 0, component);
                if (this.isOnBar(this.mColorRect, this.x1, this.y1)) {
                    this.mMovingColorBar = true;
                } else if (this.mIsShowAlphaBar && this.isOnBar(this.mAlphaRect, this.x1, this.y1)) {
                    this.mMovingAlphaBar = true;
                }
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                this.mMovingColorBar = false;
                this.mMovingAlphaBar = false;
                break;
            case TouchEvent.POINT_MOVE:
                this.x1 = getTouchX(touchEvent, touchEvent.getIndex(), component);
                this.y1 = getTouchY(touchEvent, touchEvent.getIndex(), component);
                float value;
                if (this.mMovingColorBar) {
                    value = (this.x1 - (float)this.realLeft) / (float)this.mBarWidth * (float)this.mMaxValue;
                    this.mColorBarValue = (int)value;
                    if (this.mColorBarValue < 0) {
                        this.mColorBarValue = 0;
                    }

                    if (this.mColorBarValue > this.mMaxValue) {
                        this.mColorBarValue = this.mMaxValue;
                    }
                } else if (this.mIsShowAlphaBar && this.mMovingAlphaBar) {
                    value = (this.x1 - (float)this.realLeft) / (float)this.mBarWidth * 1.0f;
                    this.mAlphaBarValue = (int)value;
                    if (this.mAlphaBarValue < 0) {
                        this.mAlphaBarValue = 0;
                    }
                    if (this.mAlphaBarValue > 1) {
                        this.mAlphaBarValue = 1;
                    }
                    this.setAlphaValue();
                }

                if (this.mOnColorChangeLister != null && (this.mMovingAlphaBar || this.mMovingColorBar)) {
                    this.mOnColorChangeLister.onColorChangeListener(this.mColorBarValue, this.mAlphaBarValue, this.getColor());
                }

                this.invalidate();
        }
        return true;
    }

    private float getTouchX(TouchEvent touchEvent, int index, Component component) {
        float touchX = 0;
        if (touchEvent.getPointerCount() > index) {
            int[] xy = component.getLocationOnScreen();
            if (xy != null && xy.length == 2) {
                touchX = touchEvent.getPointerScreenPosition(index).getX() - xy[0];
            } else {
                touchX = touchEvent.getPointerPosition(index).getX();
            }
        }
        return touchX;
    }

    private float getTouchY(TouchEvent touchEvent, int index, Component component) {
        float touchY = 0;
        if (touchEvent.getPointerCount() > index) {
            touchY = touchEvent.getPointerPosition(index).getY();
        }
        return touchY;
    }

    private boolean isOnBar(Rect r, float x, float y) {
        return (float)r.left - this.mThumbRadius < x && x < (float)r.right + this.mThumbRadius && (float)r.top - this.mThumbRadius < y && y < (float)r.bottom + this.mThumbRadius;
    }

    private int pickColor(float position) {
        float unit = position / (float)this.mBarWidth;
        if ((double)unit <= 0.0D) {
            return this.mColors[0];
        } else if (unit >= 1.0F) {
            return this.mColors[this.mColors.length - 1];
        } else {
            float colorPosition = unit * (float)(this.mColors.length - 1);
            int i = (int)colorPosition;
            colorPosition -= (float)i;
            System.out.println("mColors:" + this.mColors.length);
            this.c0 = this.mColors[i];
            this.c1 = this.mColors[i + 1];
            this.mRed = this.mix(RgbColor.fromArgbInt(this.c0).getRed(), RgbColor.fromArgbInt(this.c1).getRed(), colorPosition);
            this.mGreen = this.mix(RgbColor.fromArgbInt(this.c0).getGreen(), RgbColor.fromArgbInt(this.c1).getGreen(), colorPosition);
            this.mBlue = this.mix(RgbColor.fromArgbInt(this.c0).getBlue(), RgbColor.fromArgbInt(this.c1).getBlue(), colorPosition);
            return Color.rgb(this.mRed, this.mGreen, this.mBlue);
        }
    }

    private int mix(int start, int end, float position) {
        return start + Math.round(position * (float)(end - start));
    }

    /**
     * getColor方法
     *
     * @return this.mIsShowAlphaBar
     */
    public int getColor() {
        return this.mIsShowAlphaBar ? Color.argb((int)this.mAlpha, this.mRed, this.mGreen, this.mBlue) : Color.rgb(this.mRed, this.mGreen, this.mBlue);
    }

    /**
     * getAlphaValue()
     *
     * @return this.mAlpha
     */
    public float getAlphaValue() {
        return this.mAlpha;
    }

    /**
     * getColorWithAlpha
     *
     * @return Color.argb((int)this.mAlpha, this.mRed, this.mGreen, this.mBlue)
     */
    public int getColorWithAlpha() {
        return Color.argb((int)this.mAlpha, this.mRed, this.mGreen, this.mBlue);
    }

    /**
     * setOnColorChangeListener
     *
     * @param onColorChangeListener
     */
    public void setOnColorChangeListener(OnColorChangeListener onColorChangeListener) {
        this.mOnColorChangeLister = onColorChangeListener;
    }

    /**
     * dp2px方法
     *
     * @param context
     * @param dpValue
     * @return (int)(dpValue * displayAttributes.scalDensity)
     */
    protected int dp2px(Context context, float dpValue) {
        DisplayAttributes displayAttributes = getScreenPiex(context);
        return (int)(dpValue * displayAttributes.scalDensity);
    }

    /**
     * getScreenPiex方法
     *
     * @param context
     * @return displayAttributes
     */
    public static DisplayAttributes getScreenPiex(Context context) {
        Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context);
        DisplayAttributes displayAttributes = null;
        if (display.isPresent()) {
            displayAttributes = display.get().getAttributes();
        }
        return displayAttributes;
    }

    /**
     * setColors(int resId)方法
     *
     * @param resId
     */
    public void setColors(int resId) {
        this.setColors(this.getColorsById(resId));
    }

    /**
     * setColors(int[] colors)
     *
     * @param colors
     */
    public void setColors(int[] colors) {
        this.mColors = (int[])colors.clone();
        this.invalidate();
        this.setAlphaValue();
        if (this.mOnColorChangeLister != null) {
            this.mOnColorChangeLister.onColorChangeListener(this.mColorBarValue, this.mAlphaBarValue, this.getColor());
        }

    }

    /**
     * getColors()方法
     *
     * @return (int[])this.mColors
     */
    public int[] getColors() {
        return (int[])this.mColors;
    }

    /**
     * isShowAlphaBar
     *
     * @return this.mIsShowAlphaBar
     */
    public boolean isShowAlphaBar() {
        return this.mIsShowAlphaBar;
    }

    private void refreshLayoutParams() {
        this.mThumbHeight = this.mThumbHeight < 2 ? 2 : this.mThumbHeight;
        this.mBarHeight = this.mBarHeight < 2 ? 2 : this.mBarHeight;
        int singleHeight = this.mThumbHeight + this.mBarHeight;
        int doubleHeight = this.mThumbHeight * 2 + this.mBarHeight * 2 + this.mBarMargin;
        if (this.getLayoutConfig().height == -2) {
            if (this.mIsShowAlphaBar) {
                this.getLayoutConfig().height = doubleHeight;
                this.setLayoutConfig(this.getLayoutConfig());
            } else {
                this.getLayoutConfig().height = singleHeight;
                this.setLayoutConfig(this.getLayoutConfig());
            }
        } else if (this.getLayoutConfig().height >= 0) {
            if (this.mIsShowAlphaBar) {
                this.getLayoutConfig().height = doubleHeight;
                this.setLayoutConfig(this.getLayoutConfig());
            } else {
                this.getLayoutConfig().height = singleHeight;
                this.setLayoutConfig(this.getLayoutConfig());
            }
        }

    }

    /** 设置setShowAlphaBar
     *
     * @param show
     */
    public void setShowAlphaBar(boolean show) {
        this.mIsShowAlphaBar = show;
        this.refreshLayoutParams();
        this.invalidate();
        if (this.mOnColorChangeLister != null) {
            this.mOnColorChangeLister.onColorChangeListener(this.mColorBarValue, this.mAlphaBarValue, this.getColor());
        }

    }

    /**
     * setBarHeight(float dp)
     *
     * @param dp
     */
    public void setBarHeight(float dp) {
        this.mBarHeight = this.dp2px(mContext, dp);
        this.refreshLayoutParams();
        this.invalidate();
    }

    /**
     * setBarHeightPx(int px)
     *
     * @param px
     */
    public void setBarHeightPx(int px) {
        this.mBarHeight = px;
        this.refreshLayoutParams();
        this.invalidate();
    }

    private void setAlphaValue() {
        this.mAlpha = 1.0f - this.mAlphaBarValue;
    }

    /**
     * setAlphaBarValue
     *
     * @param value
     */
    public void setAlphaBarValue(int value) {
        this.mAlphaBarValue = value;
        this.setAlphaValue();
        this.invalidate();
    }

    /**
     * getMaxValue()
     *
     * @return this.mMaxValue
     */
    public int getMaxValue() {
        return this.mMaxValue;
    }

    /**
     * setMaxValue(int value)
     *
     * @param value
     */
    public void setMaxValue(int value) {
        this.mMaxValue = value;
        this.invalidate();
    }

    /** setBarMargin
     *
     * @param mBarMargin
     */
    public void setBarMargin(float mBarMargin) {
        this.mBarMargin = this.dp2px(mContext, mBarMargin);
        this.refreshLayoutParams();
        this.invalidate();
    }

    /** setBarMarginPx
     *
     * @param mBarMargin
     */
    public void setBarMarginPx(int mBarMargin) {
        this.mBarMargin = mBarMargin;
        this.refreshLayoutParams();
        this.invalidate();
    }

    /** setColorBarValue
     *
     * @param value
     */
    public void setColorBarValue(int value) {
        this.mColorBarValue = value;
        this.invalidate();
        if (this.mOnColorChangeLister != null) {
            this.mOnColorChangeLister.onColorChangeListener(this.mColorBarValue, this.mAlphaBarValue, this.getColor());
        }
    }

    /** setThumbHeight
     *
     * @param dp
     */
    public void setThumbHeight(float dp) {
        this.mThumbHeight = this.dp2px(mContext, dp);
        this.refreshLayoutParams();
        this.invalidate();
    }

    /** setThumbHeightPx
     *
     * @param px
     */
    public void setThumbHeightPx(int px) {
        this.mThumbHeight = px;
        this.refreshLayoutParams();
        this.invalidate();
    }

    /**
     * getBarHeight()
     *
     * @return this.mBarHeight
     */
    public int getBarHeight() {
        return this.mBarHeight;
    }

    /**
     * getThumbHeight()
     *
     * @return this.mThumbHeight
     */
    public int getThumbHeight() {
        return this.mThumbHeight;
    }

    /**
     * getBarMargin()
     *
     * @return this.mBarMargin
     */
    public int getBarMargin() {
        return this.mBarMargin;
    }

    /**
     * getColorPosition()
     *
     * @return (float)this.mColorBarValue
     */
    public float getColorPosition() {
        return (float)this.mColorBarValue;
    }

    /**
     * OnColorChangeListener
     */
    public interface OnColorChangeListener {
        /** onColorChangeListener
         *
         * @param var1
         * @param var2
         * @param var3
         */
        void onColorChangeListener(int var1, int var2, int var3);
    }
}
